package com.mhc.suzuki.service.impl;

import com.mhc.suzuki.bo.FinSettlementBO;
import com.mhc.suzuki.constant.ErrorCodeEnum;
import com.mhc.suzuki.constant.OrderStatusEnum;
import com.mhc.suzuki.dal.model.*;
import com.mhc.suzuki.dal.query.PostBankCardQuery;
import com.mhc.suzuki.dal.query.SettlementCostQuery;
import com.mhc.suzuki.exception.SuzukiCommonException;
import com.mhc.suzuki.manager.*;
import com.mhc.suzuki.service.FinSettlementService;
import com.mhc.suzuki.util.BeanCopierUtil;
import com.mhc.suzuki.vo.SettlementCostVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author Churry
 * @create 2017-08-24 15:30
 **/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class FinSettlementServiceImpl implements FinSettlementService {

    @Autowired
    OrderManager orderManager;
    @Autowired
    PostBankCardManager postBankCardManager;
    @Autowired
    DataDictManager dataDictManager;
    @Autowired
    PaymentRequestManager paymentRequestManager;
    @Autowired
    LoanInfoManager loanInfoManager;
    @Autowired
    SettlementCostManager settlementCostManager;

    /**
     * 获取订单-财务结算详情
     * @param orderNo
     * @return
     * @throws SuzukiCommonException
     */
    @Override
    public FinSettlementBO getFinSettlementDetail(String orderNo) throws SuzukiCommonException {
        Optional<String> orderNoOptional = Optional.ofNullable(orderNo);
        if (orderNoOptional.isPresent()) {
            FinSettlementBO finSettlementBO = new FinSettlementBO();
            finSettlementBO.setOrderNo(orderNo);
            try {
                //获取银行账户信息与银行放款信息
                OrderDO orderDO = orderManager.selectByOrderNo(orderNo);
                PostBankCardDO postBankCardDO = postBankCardManager.selectByOrderNo(orderNo);
                Optional<PostBankCardDO> postBankCardDOOptional = Optional.ofNullable(postBankCardDO);
                LoanInfoDO loanInfoDO = loanInfoManager.selectByOrderNo(orderNo);
                DataDictDO dataDictDO = dataDictManager.selectByPrimaryKey(loanInfoDO.getBankId());
                finSettlementBO.setCustomerName(orderDO.getCustomerName());
                finSettlementBO.setBankName(dataDictDO.getName());
                finSettlementBO.setRepayAccount(postBankCardDOOptional.orElse(new PostBankCardDO()).getRepayAccount());
                //贷款金额的更改即时生效，所以实际垫资金额就是贷款金额
                finSettlementBO.setActualLoaningAmount(loanInfoDO.getLoanAmount());
                finSettlementBO.setBankLoanDate(loanInfoDO.getBankLoanDate());
                finSettlementBO.setBankLoanAmount(loanInfoDO.getBankLoanAmount());
                finSettlementBO.setRemark(loanInfoDO.getRemark());
            } catch (Exception e) {
                log.error("获取银行账户信息失败,orderNO="+orderNo, e);
                throw new SuzukiCommonException(ErrorCodeEnum.QUERY_BANK_INFO_FAIL);
            }
            //获取垫款信息
            PaymentRequestDO paymentRequestDO = paymentRequestManager.selectByOrderNo(orderNo);
            if(paymentRequestDO == null){
                log.error("获取垫款信息失败,orderNO="+orderNo);
                throw new SuzukiCommonException(ErrorCodeEnum.PAYMENT_REQUEST_ISNULL);
            }
            finSettlementBO.setLoaningDate(paymentRequestDO.getLoaningDate());
            //财务垫款后，垫款信息不再变化，所以垫资金额就是打款表的垫款金额
            finSettlementBO.setLoaningAmount(paymentRequestDO.getLoaningAmount());

            //获取费用信息,费用信息可以为空（尚未录入的时候），所以不抛出为空异常
            List<SettlementCostVO> settlementCostVOList = new ArrayList<>();
            List<SettlementCostDO> settlementCostDOList = settlementCostManager.selectByOrderNo(orderNo);
            if(CollectionUtils.isNotEmpty(settlementCostDOList)) {
                for (SettlementCostDO settlementCostDO : settlementCostDOList) {
                    SettlementCostVO settlementCostVO = BeanCopierUtil.convert(settlementCostDO, SettlementCostVO.class);
                    settlementCostVOList.add(settlementCostVO);
                }
            }
            finSettlementBO.setSettlementCostList(settlementCostVOList);
            return finSettlementBO;
        } else {
            throw new SuzukiCommonException(ErrorCodeEnum.ORDER_NO_ISNULL);
        }
    }

    /**
     * 保存订单-财务结算详情
     * @param staffId
     * @param finSettlementBO
     * @param orderNo
     * @return
     * @throws SuzukiCommonException
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean saveFinSettlementDetail(Long staffId, FinSettlementBO finSettlementBO, String orderNo) throws SuzukiCommonException {
        Optional<String> orderNoOptional = Optional.ofNullable(orderNo);
        if (orderNoOptional.isPresent()) {
            OrderDO orderDO = orderManager.selectByOrderNo(orderNo);
            Optional<LocalDateTime> bankLoanDateOptional = Optional.ofNullable(finSettlementBO.getBankLoanDate());
            Optional<BigDecimal> bankLoanAmountOptional = Optional.ofNullable(finSettlementBO.getBankLoanAmount());
            //如果订单状态是财务已垫款或银行已放款，收到的数据有银行放款信息时，则设置订单状态为银行已放款，并更新贷款信息
            boolean orderStatusCodition = OrderStatusEnum.ALREADY_PAYMENT.getCode().equals(orderDO.getOrderStatus())
                    || OrderStatusEnum.BANK_YET_LENDING.getCode().equals(orderDO.getOrderStatus());
            if (orderStatusCodition && bankLoanDateOptional.isPresent() && bankLoanAmountOptional.isPresent()) {
                orderDO.setOrderStatus(OrderStatusEnum.BANK_YET_LENDING.getCode());
                try {
                    orderManager.updateByPrimaryKeySelective(orderDO);
                } catch (Exception e) {
                    log.error("更新订单状态为银行已放款失败,orderNO="+orderNo, e);
                    throw new SuzukiCommonException(ErrorCodeEnum.UPDATA_ORDER_STATUS_BANK_YET_LENDING_FAIL);
                }
                try {
                    //保存放款信息
                    LoanInfoDO loanInfoDO = loanInfoManager.selectByOrderNo(orderNo);
                    loanInfoDO.setBankLoanDate(finSettlementBO.getBankLoanDate());
                    loanInfoDO.setBankLoanAmount(finSettlementBO.getBankLoanAmount());
                    loanInfoDO.setRemark(finSettlementBO.getRemark());
                    loanInfoDO.setStaffId(staffId);
                    loanInfoManager.updateByPrimaryKeySelective(loanInfoDO);
                } catch (Exception e) {
                    log.error("保存放款信息失败,orderNo="+orderNo, e);
                    throw new SuzukiCommonException(ErrorCodeEnum.INSERT_LOANINFO_FAIL);
                }
            }
            try {
                //删除更新前可能已存在的旧数据
                SettlementCostQuery settlementCostQuery = new SettlementCostQuery();
                settlementCostQuery.createCriteria().andOrderNoEqualTo(orderNo);
                settlementCostManager.deleteByQuery(settlementCostQuery);
                //保存费用信息
                for (SettlementCostVO settlementCostVO : finSettlementBO.getSettlementCostList()) {
                    settlementCostVO.setStaffId(staffId);
                    settlementCostManager.insertSelective(BeanCopierUtil.convert(settlementCostVO, SettlementCostDO.class));
                }
            } catch (Exception e) {
                log.error("保存费用信息失败,orderNo="+orderNo, e);
                throw new SuzukiCommonException(ErrorCodeEnum.INSERT_SETTLEMENT_COST_FAIL);
            }
            try {
                //保存寄卡信息中的还款信用卡号
                PostBankCardDO postBankCardDO = new PostBankCardDO();
                PostBankCardQuery postBankCardQuery = new PostBankCardQuery();
                postBankCardDO.setRepayAccount(finSettlementBO.getRepayAccount());
                postBankCardQuery.createCriteria().andOrderNoEqualTo(orderNo);
                postBankCardManager.updateByQuerySelective(postBankCardDO,postBankCardQuery);
            } catch (Exception e) {
                log.error("保存还款信用卡号失败,orderNo="+orderNo, e);
                throw new SuzukiCommonException(ErrorCodeEnum.UPDATE_REPAYACCOUNT_FAIL);
            }
            return true;
        } else {
            throw new SuzukiCommonException(ErrorCodeEnum.ORDER_NO_ISNULL);
        }
    }


}
